from PyQt6.QtWidgets import (QWidget, QVBoxLayout, QPushButton, 
                           QLabel, QFileDialog, QProgressBar,
                           QListWidget, QHBoxLayout, QMessageBox,
                           QListWidgetItem, QStyle, QMenu, QTextEdit)
from PyQt6.QtCore import Qt, pyqtSignal, QObject, QMimeData, QSize, QTimer
from PyQt6.QtGui import QFont, QIcon, QPixmap, QDragEnterEvent, QDropEvent, QImage
import os
from datetime import datetime
from utils.converter import FileConverter  # 添加导入

class SignalEmitter(QObject):
    """信号发射器"""
    progress_signal = pyqtSignal(int)
    error_signal = pyqtSignal(str)
    complete_signal = pyqtSignal()

class DocumentListWidget(QListWidget):
    """自定义文档列表控件"""
    def __init__(self, parent=None):
        super().__init__(parent)
        # 设置为图标模式
        self.setViewMode(QListWidget.ViewMode.IconMode)
        # 设置图标大小
        self.setIconSize(QSize(40, 40))
        # 设置间距
        self.setSpacing(20)
        # 设置自动调整
        self.setResizeMode(QListWidget.ResizeMode.Adjust)
        # 设置换行
        self.setWrapping(True)
        # 设置拖拽模式
        self.setDragDropMode(QListWidget.DragDropMode.InternalMove)
        # 设置选择模式
        self.setSelectionMode(QListWidget.SelectionMode.ExtendedSelection)
        # 设置统一的项目大小
        self.setGridSize(QSize(120, 140))
        # 设置移动模式
        self.setMovement(QListWidget.Movement.Snap)
        # 设置布局模式
        self.setFlow(QListWidget.Flow.LeftToRight)
        # 设置对齐方式
        self.setLayoutMode(QListWidget.LayoutMode.Batched)

        # 添加计时器用于延迟刷新
        self.update_timer = QTimer(self)
        self.update_timer.setSingleShot(True)
        self.update_timer.timeout.connect(self.forceLayoutUpdate)

        # 启用右键菜单
        self.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu)
        self.customContextMenuRequested.connect(self.show_context_menu)
        
        # 启用双击删除
        self.itemDoubleClicked.connect(self.remove_item)

        self.setStyleSheet("""
            QListWidget {
                border: 2px dashed #CCCCCC;
                border-radius: 4px;
                padding: 20px;
                background: white;
            }
            QListWidget::item {
                border: 1px solid #EEEEEE;
                border-radius: 4px;
                background: white;
                color: #333333;
                margin: 5px;
            }
            QListWidget::item:selected {
                background: #ECF2FF;
                border: 1px solid #2B579A;
            }
            QListWidget::item:hover {
                background: #F5F8FF;
                border: 1px solid #A8C0FF;
            }
        """)

    def forceLayoutUpdate(self):
        """强制更新布局和视图"""
        self.setSpacing(self.spacing())
        self.viewport().update()
        self.scrollToItem(self.currentItem())

    def dragMoveEvent(self, event):
        """处理拖动过程中鼠标移动事件"""
        if not self.itemAt(event.position().toPoint()):
            super().dragMoveEvent(event)
            return

        pos = event.position().toPoint()
        source_item = self.currentItem()
        target_item = self.itemAt(pos)

        if target_item and source_item != target_item:
            target_row = self.row(target_item)
            source_row = self.row(source_item)
            
            self.takeItem(source_row)
            self.insertItem(target_row, source_item)
            self.setCurrentItem(source_item)
            
            self.viewport().update()
            self.scrollToItem(source_item)

        event.accept()

    def dropEvent(self, event: QDropEvent):
        """处理拖放事件以更新文件顺序"""
        super().dropEvent(event)
        
        drop_area = self.parent()
        if hasattr(drop_area, 'document_converter') and drop_area.document_converter:
            new_files = []
            for i in range(self.count()):
                item = self.item(i)
                new_files.append(item.toolTip())
            drop_area.document_converter.selected_files = new_files
        
        self.update_timer.start(100)

    def show_context_menu(self, position):
        """显示右键菜单"""
        menu = QMenu(self)
        delete_action = menu.addAction("删除")
        delete_action.triggered.connect(lambda: self.remove_item(self.itemAt(position)))
        menu.exec(self.mapToGlobal(position))

    def remove_item(self, item):
        """删除列表项"""
        if not item:
            return
            
        reply = QMessageBox.question(
            self,
            "确认删除",
            f"确定要删除文件 {item.text()} 吗？",
            QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No,
            QMessageBox.StandardButton.No
        )
        
        if reply == QMessageBox.StandardButton.Yes:
            row = self.row(item)
            item = self.takeItem(row)
            
            drop_area = self.parent()
            if hasattr(drop_area, 'document_converter') and drop_area.document_converter:
                file_path = item.toolTip()
                if file_path in drop_area.document_converter.selected_files:
                    drop_area.document_converter.selected_files.remove(file_path)
                    
                if self.count() == 0:
                    drop_area.show_hint()
                    drop_area.document_converter.status_label.setText("")
                else:
                    drop_area.document_converter.status_label.setText(f"已删除文件：{item.text()}")
                
                drop_area.document_converter.update_convert_button()

class DropArea(QWidget):
    """自定义拖拽区域"""
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setAcceptDrops(True)
        self.document_converter = None
        
        layout = QVBoxLayout(self)
        layout.setContentsMargins(0, 0, 0, 0)
        layout.setSpacing(0)
        
        self.list_widget = DocumentListWidget(self)
        
        self.hint_label = QLabel("拖拽文档到此处或点击\"选择文件\"按钮")
        self.hint_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
        self.hint_label.setStyleSheet("""
            QLabel {
                color: #999999;
                padding: 20px;
                font-size: 14px;
                background: transparent;
            }
        """)
        
        layout.addWidget(self.list_widget)
        
        self.hint_label.setParent(self.list_widget)
        
        def resizeEvent(event):
            super(self.list_widget.__class__, self.list_widget).resizeEvent(event)
            self.hint_label.setGeometry(
                0, 0,
                self.list_widget.width(),
                self.list_widget.height()
            )
        
        self.list_widget.resizeEvent = resizeEvent
        
        self.hint_label.raise_()
    
    def show_hint(self):
        """显示提示文字"""
        self.hint_label.show()
    
    def hide_hint(self):
        """隐藏提示文字"""
        self.hint_label.hide()

    def dragEnterEvent(self, event: QDragEnterEvent):
        """处理拖拽进入事件"""
        if event.mimeData().hasUrls():
            event.acceptProposedAction()
    
    def dropEvent(self, event: QDropEvent):
        """处理文件拖放"""
        files = []
        for url in event.mimeData().urls():
            file_path = url.toLocalFile()
            # 检查文件扩展名是否支持
            ext = os.path.splitext(file_path)[1].lower()
            if any(ext == supported.replace('*', '') 
                  for supported in self.document_converter.SUPPORTED_FORMATS):
                files.append(file_path)
        
        if files:
            # 如果还未设置保存路径，则设置默认保存路径
            if not self.document_converter.save_path:
                self.document_converter.save_path = os.path.dirname(files[0])
                self.document_converter.save_path_label.setText(
                    f"保存位置: {self.document_converter.save_path}"
                )
            
            # 添加文件到列表
            for file in files:
                if file not in self.document_converter.selected_files:
                    self.document_converter.selected_files.append(file)
                    self.document_converter.add_file_item(file)
            
            self.document_converter.update_convert_button()
            self.document_converter.status_label.setText(f"已添加 {len(files)} 个文件，可以开始转换")
            self.hide_hint()

class DocumentConverterWidget(QWidget):
    # 支持的文件格式
    SUPPORTED_FORMATS = [
        "*.doc", "*.docx",    # Word文档
        "*.xls", "*.xlsx",    # Excel文档
        "*.ppt", "*.pptx",    # PowerPoint文档
        "*.txt", "*.rtf",     # 文本文档
        "*.md", "*.sql",      # Markdown和SQL文件
        "*.html", "*.log",    # HTML和日志文件
        "*.odt", "*.ods",     # OpenOffice文档
        "*.jpg", "*.jpeg", "*.png", "*.bmp",  # 图片文件
        "*.pdf"               # PDF文件
    ]

    def __init__(self, title="文档转PDF", description="将文档转换为PDF格式"):
        super().__init__()
        self.title = title
        # 更新描述，包含支持的格式信息
        self.description = (
            f"{description}\n支持的格式：Word文档(doc, docx), Excel(xls, xlsx), "
            "PPT(ppt, pptx), 文本文件(txt, rtf), OpenOffice(odt, ods), "
            "图片文件(jpg, jpeg, png, bmp)"
        )
        self.selected_files = []
        self.save_path = None
        
        # 创建信号发射器
        self.signal_emitter = SignalEmitter()
        self.signal_emitter.progress_signal.connect(self.on_progress_update)
        self.signal_emitter.error_signal.connect(self.on_error)
        self.signal_emitter.complete_signal.connect(self.on_conversion_complete)
        
        self.init_ui()
    
    def init_ui(self):
        layout = QVBoxLayout(self)
        layout.setContentsMargins(20, 20, 20, 20)
        
        # 标题
        title = QLabel(self.title)
        title.setFont(QFont("Arial", 16, QFont.Weight.Bold))
        layout.addWidget(title)
        
        # 说明文字（使用QTextEdit以支持多行和自动换行）
        desc = QTextEdit()
        desc.setPlainText(self.description)
        desc.setReadOnly(True)
        desc.setMaximumHeight(80)
        desc.setStyleSheet("""
            QTextEdit {
                color: #666666;
                background: transparent;
                border: none;
                font-size: 12px;
            }
        """)
        layout.addWidget(desc)
        
        # 文件选择区域
        file_area = QHBoxLayout()
        self.select_btn = QPushButton("选择文件")
        self.select_btn.setStyleSheet("""
            QPushButton {
                background-color: #2B579A;
                color: white;
                padding: 8px 16px;
                border-radius: 4px;
            }
            QPushButton:hover {
                background-color: #1E3F7F;
            }
        """)
        self.select_btn.clicked.connect(self.select_files)
        file_area.addWidget(self.select_btn)
        
        self.clear_btn = QPushButton("清空列表")
        self.clear_btn.setStyleSheet("""
            QPushButton {
                padding: 8px 16px;
                border-radius: 4px;
                border: 1px solid #CCCCCC;
            }
            QPushButton:hover {
                background-color: #f5f5f5;
            }
        """)
        self.clear_btn.clicked.connect(self.clear_list)
        file_area.addWidget(self.clear_btn)
        
        file_area.addStretch()
        layout.addLayout(file_area)
        
        # 拖拽区域
        self.drop_area = DropArea(self)
        self.drop_area.document_converter = self
        layout.addWidget(self.drop_area)
        
        # 保存路径选择
        save_area = QHBoxLayout()
        self.save_path_label = QLabel("未选择保存位置")
        self.save_path_label.setStyleSheet("color: #666666;")
        save_area.addWidget(self.save_path_label)
        
        self.save_btn = QPushButton("选择路径")
        self.save_btn.setStyleSheet("""
            QPushButton {
                background-color: #2B579A;
                color: white;
                padding: 8px 16px;
                border-radius: 4px;
            }
            QPushButton:hover {
                background-color: #1E3F7F;
            }
        """)
        self.save_btn.clicked.connect(self.select_save_path)
        save_area.addWidget(self.save_btn)
        layout.addLayout(save_area)
        
        # 转换按钮
        convert_area = QHBoxLayout()
        convert_area.addStretch()
        self.convert_btn = QPushButton("转换为PDF")
        self.convert_btn.setMinimumWidth(120)
        self.convert_btn.setStyleSheet("""
            QPushButton {
                background-color: #2B579A;
                color: white;
                padding: 8px 16px;
                border-radius: 4px;
            }
            QPushButton:hover {
                background-color: #1E3F7F;
            }
            QPushButton:disabled {
                background-color: #CCCCCC;
            }
        """)
        self.convert_btn.clicked.connect(self.start_convert)
        self.convert_btn.setEnabled(False)
        convert_area.addWidget(self.convert_btn)
        layout.addLayout(convert_area)
        
        # 进度条
        self.progress_bar = QProgressBar()
        self.progress_bar.setStyleSheet("""
            QProgressBar {
                border: 1px solid #CCCCCC;
                border-radius: 4px;
                text-align: center;
            }
            QProgressBar::chunk {
                background-color: #2B579A;
            }
        """)
        self.progress_bar.hide()
        layout.addWidget(self.progress_bar)
        
        # 状态标签
        self.status_label = QLabel("")
        self.status_label.setStyleSheet("color: #666666;")
        self.status_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
        layout.addWidget(self.status_label)
        
        layout.addStretch()

    def add_file_item(self, file_path):
        """添加文件项到列表"""
        item = QListWidgetItem()
        item.setToolTip(file_path)  # 设置完整路径为提示
        
        # 根据文件类型设置不同的图标
        ext = os.path.splitext(file_path)[1].lower()
        
        # 定义文件类型图标映射
        icon_mapping = {
            '.doc': QStyle.StandardPixmap.SP_FileDialogDetailedView,   # 文档图标
            '.docx': QStyle.StandardPixmap.SP_FileDialogDetailedView,
            '.xls': QStyle.StandardPixmap.SP_FileDialogListView,       # 表格图标
            '.xlsx': QStyle.StandardPixmap.SP_FileDialogListView,
            '.ppt': QStyle.StandardPixmap.SP_FileDialogInfoView,       # 演示文稿图标
            '.pptx': QStyle.StandardPixmap.SP_FileDialogInfoView,
            '.txt': QStyle.StandardPixmap.SP_FileIcon,                 # 文本文件图标
            '.rtf': QStyle.StandardPixmap.SP_FileIcon,
            '.odt': QStyle.StandardPixmap.SP_FileDialogDetailedView,
            '.ods': QStyle.StandardPixmap.SP_FileDialogListView,
        }
        
        if ext in icon_mapping:
            icon = self.style().standardIcon(icon_mapping[ext])
        elif ext in ['.jpg', '.jpeg', '.png', '.bmp']:
            # 如果是图片，创建缩略图
            pixmap = QPixmap(file_path)
            if not pixmap.isNull():
                pixmap = pixmap.scaled(40, 40, Qt.AspectRatioMode.KeepAspectRatio, 
                                     Qt.TransformationMode.SmoothTransformation)
                icon = QIcon(pixmap)
            else:
                icon = self.style().standardIcon(QStyle.StandardPixmap.SP_FileIcon)
        else:
            icon = self.style().standardIcon(QStyle.StandardPixmap.SP_FileIcon)
        
        item.setIcon(icon)
        item.setText(os.path.basename(file_path))
        item.setTextAlignment(Qt.AlignmentFlag.AlignCenter)
        
        self.drop_area.list_widget.addItem(item)

    def select_files(self):
        """选择文件"""
        # 构建文件过滤器字符串
        filter_str = "支持的文档 ("
        filter_str += " ".join(self.SUPPORTED_FORMATS)
        filter_str += ")"
        
        files, _ = QFileDialog.getOpenFileNames(
            self,
            "选择要转换的文件",
            "",
            filter_str
        )
        
        if files:
            # 如果还未设置保存路径，则设置默认保存路径
            if not self.save_path:
                self.save_path = os.path.dirname(files[0])
                self.save_path_label.setText(f"保存位置: {self.save_path}")
            
            # 添加新文件到列表
            for file in files:
                if file not in self.selected_files:
                    self.selected_files.append(file)
                    self.add_file_item(file)
            
            self.update_convert_button()
            self.status_label.setText(f"已添加 {len(files)} 个文件，可以开始转换")
            self.drop_area.hide_hint()

    def clear_list(self):
        """清空文件列表"""
        self.drop_area.list_widget.clear()
        self.selected_files = []
        self.update_convert_button()
        self.status_label.setText("")
        self.drop_area.show_hint()

    def update_convert_button(self):
        """更新转换按钮状态"""
        self.convert_btn.setEnabled(bool(self.selected_files))

    def select_save_path(self):
        """选择保存路径"""
        path = QFileDialog.getExistingDirectory(
            self,
            "选择保存路径"
        )
        if path:
            self.save_path = path
            self.save_path_label.setText(f"保存位置: {self.save_path}")

    def start_convert(self):
        """开始转换"""
        if not self.selected_files or not self.save_path:
            return
        
        # 禁用按钮并显示进度条
        self.convert_btn.setEnabled(False)
        self.select_btn.setEnabled(False)
        self.save_btn.setEnabled(False)
        self.progress_bar.show()
        self.progress_bar.setValue(0)
        self.status_label.setText("正在转换...")
        
        # 创建临时文件夹
        temp_dir = os.path.join(self.save_path, "__temp__")
        os.makedirs(temp_dir, exist_ok=True)
        
        try:
            # 获取列表控件中的文件顺序
            ordered_files = []
            for i in range(self.drop_area.list_widget.count()):
                item = self.drop_area.list_widget.item(i)
                ordered_files.append(item.toolTip())
            
            # 为每个文件创建临时PDF
            temp_pdfs = []
            successful_conversions = []
            total_files = len(ordered_files)
            
            # 生成最终输出文件名
            timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
            final_output = os.path.join(self.save_path, f"converted_{timestamp}.pdf")
            
            # 定义文本文件扩展名列表
            TEXT_EXTENSIONS = ['.txt', '.rtf', '.md', '.sql', '.html', '.log']
            
            # 按列表顺序处理文件
            for i, file_path in enumerate(ordered_files):
                try:
                    ext = os.path.splitext(file_path)[1].lower()
                    temp_pdf = os.path.join(temp_dir, f"temp_{i}.pdf")
                    
                    # 根据文件类型选择转换方法
                    if ext == '.pdf':
                        # 如果是PDF文件，直接复制到临时目录
                        import shutil
                        shutil.copy2(file_path, temp_pdf)
                    elif ext in ['.doc', '.docx']:
                        FileConverter.convert_doc_to_pdf(file_path, temp_pdf)
                    elif ext in ['.xls', '.xlsx']:
                        FileConverter.convert_excel_to_pdf(file_path, temp_pdf)
                    elif ext in ['.ppt', '.pptx']:
                        FileConverter.convert_ppt_to_pdf(file_path, temp_pdf)
                    elif ext in ['.jpg', '.jpeg', '.png', '.bmp']:
                        FileConverter.convert_image_to_pdf(file_path, temp_pdf)
                    elif ext in TEXT_EXTENSIONS:  # 使用文本文件扩展名列表
                        FileConverter.convert_text_to_pdf(file_path, temp_pdf)
                    
                    if os.path.exists(temp_pdf):  # 确认文件已成功创建
                        temp_pdfs.append(temp_pdf)
                        successful_conversions.append(file_path)
                    
                    # 更新进度
                    progress = int((i + 1) / total_files * 90)
                    self.signal_emitter.progress_signal.emit(progress)
                    
                except Exception as e:
                    self.status_label.setText(f"转换 {os.path.basename(file_path)} 时出错: {str(e)}")
                    continue  # 继续处理下一个文件
            
            if not temp_pdfs:  # 如果没有成功转换的文件
                raise Exception("没有文件被成功转换")
            
            if len(temp_pdfs) == 1:  # 如果只有一个文件，直接复制或重命名
                if temp_pdfs[0] != final_output:  # 避免源文件和目标文件相同
                    import shutil
                    shutil.copy2(temp_pdfs[0], final_output)
            else:  # 多个文件需要合并
                try:
                    FileConverter.merge_pdfs(temp_pdfs, final_output)
                except Exception as e:
                    # 如果合并失败，但至少有一个文件转换成功
                    if len(successful_conversions) == 1:
                        import shutil
                        shutil.copy2(temp_pdfs[0], final_output)
                    else:
                        raise Exception(f"PDF合并失败: {str(e)}")
            
            # 清理临时文件夹
            try:
                import shutil
                shutil.rmtree(temp_dir)
            except:
                pass  # 忽略删除临时文件夹时的错误
            
            if os.path.exists(final_output):  # 确认最终文件已创建
                self.signal_emitter.progress_signal.emit(100)
                self.signal_emitter.complete_signal.emit()
            else:
                raise Exception("转换完成，但未找到输出文件")
            
        except Exception as e:
            # 清理临时文件夹
            try:
                import shutil
                shutil.rmtree(temp_dir)
            except:
                pass
            self.signal_emitter.error_signal.emit(str(e))

    def on_progress_update(self, progress):
        """处理进度更新"""
        self.progress_bar.setValue(progress)

    def on_error(self, error_message):
        """处理错误"""
        QMessageBox.critical(
            self,
            "转换错误",
            f"转换过程中发生错误：\n{error_message}"
        )
        self.reset_interface()

    def on_conversion_complete(self):
        """处理转换完成"""
        QMessageBox.information(
            self,
            "转换完成",
            f"文件已成功转换为PDF！\n保存位置：{self.save_path}"
        )
        self.reset_interface()

    def reset_interface(self):
        """重置界面"""
        self.progress_bar.hide()
        self.status_label.setText("")
        self.convert_btn.setEnabled(True)
        self.select_btn.setEnabled(True)
        self.save_btn.setEnabled(True) 